Stuff to install first

This tutorial is based on the air quality kit tutorial available from Particle. I strongly recommend reading through that tutorial before you get started.

Get started: assembling and pairing your device

I’ve put together a Youtube video that will help you assemble your device: Assembling and Pairing Particle Microcontroller

Great, so now you’ve put together your device it’s time to program your device.

Programming your Particle Argon microcontroller

Now that you have the device assembled and paired, you want to plug it into the computer using the USB cable that was supplied. Next open up the Particle Workbench (do this by opening Visual Studio Code – commonly referred to as VS Code). When you’ve done that, you’ll be ready to follow along with the tutorial in this next video. I recommend watching the video and then try it for yourself with the air quality kit tutorial and the video as reference. Programming your Particle Argon

Okay, now that you’ve completed the work in this video, your sensor package is collecting data and sending those data to the cloud. The problem is that now we have to actually save our data to the cloud somewhere. That’s the next exciting part.

I tried to follow the tutorial and video, but I’m getting stuck

That’s totally fine. I’ve included a working version of the code below. Watch this video and I’ll explain how to get started very quickly using this code snippet.

NOTE: The point of this class is to learn how to use these devices in a functional matter. That means I suggest at least trying to work through the code as I describe above and is in the tutorial. That said, it is a little tricky and because we are working remotely it’s not as easy to work through problems remotely. So if you give the above information a shot and it doesn’t work, go ahead and use the script below, but do try to work through the material above – I think you’ll find it beneficial.

Here’s the video explaining how to load the code snippet below onto your Particle Argon: Quickly Programming your Particle

Here’s the code that you past into VS Code following the instructions in the video:

/*
 * Project Argon_Tutorial
 * Description:
 * Author:
 * Date:
 */


#include "Air_Quality_Sensor.h"
#include "Adafruit_BME280.h"
#include "Adafruit_Sensor.h"
#include "SeeedOLED.h"
#include "JsonParserGeneratorRK.h"


#define DUST_SENSOR_PIN D4
#define SENSOR_READING_INTERVAL 30000
#define AQS_PIN A2

AirQualitySensor aqSensor(AQS_PIN);
Adafruit_BME280 bme;


unsigned long lastInterval;
unsigned long lowpulseoccupancy = 0;
unsigned long last_lpo = 0;
unsigned long duration;

float ratio = 0;
float concentration = 0;



// setup() runs once, when the device is first turned on.
void setup() {
   Serial.begin(9600);
   
   //Initialize OLED Screen
   Wire.begin();
   SeeedOled.init();

   SeeedOled.clearDisplay();
   SeeedOled.setNormalDisplay();
   SeeedOled.setPageMode();

   //OLED Startup Message
   SeeedOled.setTextXY(2, 0);
   SeeedOled.putString("Ready");
   SeeedOled.setTextXY(3, 0);
   SeeedOled.putString("to");
   SeeedOled.setTextXY(4, 0);
   SeeedOled.putString("Rock and Roll");

   pinMode(DUST_SENSOR_PIN, INPUT);
   lastInterval = millis();


   //checking to see if the air quality sensor is ready.
   if (aqSensor.init())
   {
      Serial.println("Air Quality Sensor ready.");
    }
   else
   {
      Serial.println("Air Quality Sensor ERROR!");
   }


   //checking to see if the BME sensor is ready.
   if (bme.begin())
   {
      Serial.println("BME280 Sensor ready.");
   }
   else
   {
      Serial.println("BME280 Sensor ERROR!");
   }



}






// loop() runs over and over again, as quickly as it can execute.
void loop() {
int temp, pressure, humidity;   
duration = pulseIn(DUST_SENSOR_PIN, LOW);
lowpulseoccupancy = lowpulseoccupancy + duration;

if ((millis() - lastInterval) > SENSOR_READING_INTERVAL)
{
   getDustSensorReadings();

   lowpulseoccupancy = 0;
   lastInterval = millis();


   //This is the air quality code
   String quality = getAirQuality();
   Serial.printlnf("Air Quality: %s", quality.c_str());

   getBMEValues(temp, pressure, humidity);
   Serial.printlnf("Temp: %d", temp);
   Serial.printlnf("Pressure: %d", pressure);
   Serial.printlnf("Humidity: %d", humidity);
   updateDisplay(temp, humidity, pressure, quality);
   createEventPayload(temp, humidity, pressure, quality);
}

}






// This function gets readings from the dust sensor.
void getDustSensorReadings()
{
if (lowpulseoccupancy == 0)
{
 lowpulseoccupancy = last_lpo;
}
else
{
 last_lpo = lowpulseoccupancy;
}

ratio = lowpulseoccupancy / (SENSOR_READING_INTERVAL * 10.0);
concentration = 1.1 * pow(ratio, 3) - 3.8 * pow(ratio, 2) + 520 * ratio + 0.62;

Serial.printlnf("LPO: %d", lowpulseoccupancy);
Serial.printlnf("Ratio: %f%%", ratio);
Serial.printlnf("Concentration: %f pcs/L", concentration);


}





//This is a function to run the air quality sensor.
String getAirQuality()
{
 int quality = aqSensor.slope();
 String qual = "None";

 if (quality == AirQualitySensor::FORCE_SIGNAL)
 {
   qual = "Danger";
 }
 else if (quality == AirQualitySensor::HIGH_POLLUTION)
 {
   qual = "High Pollution";
 }
 else if (quality == AirQualitySensor::LOW_POLLUTION)
 {
   qual = "Low Pollution";
 }
 else if (quality == AirQualitySensor::FRESH_AIR)
 {
   qual = "Fresh Air";
 }

 return qual;
}

//function to weather data from BME sensor
int getBMEValues(int &temp, int &pressure, int &humidity)
{
 temp = (int)bme.readTemperature();
 pressure = (int)(bme.readPressure() / 100.0F);
 humidity = (int)bme.readHumidity();

 return 1;
}



//function to run OLED display.
void updateDisplay(int temp, int humidity, int pressure, String airQuality)
{
 SeeedOled.clearDisplay();

 SeeedOled.setTextXY(0, 3);
 SeeedOled.putString(airQuality);

 SeeedOled.setTextXY(2, 0);
 SeeedOled.putString("Temp: ");
 SeeedOled.putNumber(temp);
 SeeedOled.putString("C");

 SeeedOled.setTextXY(3, 0);
 SeeedOled.putString("Humidity: ");
 SeeedOled.putNumber(humidity);
 SeeedOled.putString("%");

 SeeedOled.setTextXY(4, 0);
 SeeedOled.putString("Press: ");
 SeeedOled.putNumber(pressure);
 SeeedOled.putString(" hPa");

 if (concentration > 1)
 {
   SeeedOled.setTextXY(5, 0);
   SeeedOled.putString("Dust: ");
   SeeedOled.putNumber(concentration); // Cast our float to an int to make it more compact
   SeeedOled.putString(" pcs/L");
 }
}


//function for JSON payload.
void createEventPayload(int temp, int humidity, int pressure, String airQuality)
{
  JsonWriterStatic<256> jw;
  {
  JsonWriterAutoObject obj(&jw);

  jw.insertKeyValue("temp", temp);
  jw.insertKeyValue("humidity", humidity);
  jw.insertKeyValue("pressure", pressure);
  jw.insertKeyValue("air-quality", airQuality);

  if (lowpulseoccupancy > 0)
  {
   jw.insertKeyValue("dust-lpo", lowpulseoccupancy);
   jw.insertKeyValue("dust-ratio", ratio);
   jw.insertKeyValue("dust-concentration", concentration);
  }
  Particle.publish("env-vals", jw.getBuffer(), PRIVATE);
}
}